package com.hp.team.bookstore.web.order;

import java.util.Calendar;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.hp.team.bookstore.model.catalog.Product;
import com.hp.team.bookstore.model.order.SOStatus;
import com.hp.team.bookstore.model.order.SalesOrder;
import com.hp.team.bookstore.model.order.SalesOrderItem;
import com.hp.team.bookstore.model.profile.CreditCard;
import com.hp.team.bookstore.model.profile.Customer;
import com.hp.team.bookstore.model.profile.User;
import com.hp.team.bookstore.service.catalog.ProductService;
import com.hp.team.bookstore.service.exception.BadOperationException;
import com.hp.team.bookstore.service.order.SalesOrderService;
import com.hp.team.bookstore.service.profile.ProfileService;
import com.hp.team.bookstore.web.IPageUrlConstants;

@Controller
@SessionAttributes(value = { "orders", "ordersAll", "title", "shoppingCartList", "selectedCustomer", "paymentType",
		"selectedCreditCard", "customerCreditCards" })
public class SalesOrderController implements IPageUrlConstants {

	@Autowired
	public SalesOrderService salesOrderService;

	@Autowired
	private ProductService productService;

	@Autowired
	private ProfileService profileService;

	private Map<Product, Integer> shoppingCartList = new TreeMap<Product, Integer>();

	@RequestMapping(value = "/so_list")
	public String listAllOrders(ModelMap model, @RequestParam String role, @RequestParam String operation, @RequestParam String title) throws BadOperationException {

		// TODO: Check the passed role against role of the current user - the
		// current user should be saved in the session

		Map<SalesOrder, Set<SOStatus>> ordersMap = salesOrderService.getOrdersMap(role, operation);

		model.addAttribute("orders", ordersMap);
		model.addAttribute("ordersAll", ordersMap);
		model.addAttribute("title", title);
		return PAGE_SALES_ORDER_LIST;
	}

	@RequestMapping(value = "/so_list_back_all")
	public String listAllOrders(ModelMap model, @ModelAttribute("ordersAll") Map<SalesOrder, Set<SOStatus>> orders) {
		model.addAttribute("orders", orders);
		return PAGE_PURCHASE_ORDER_LIST;
	}

	@RequestMapping(value = "/so_list_back")
	public String listOrders(ModelMap model, @ModelAttribute("orders") Map<SalesOrder, Set<SOStatus>> orders) {
		model.addAttribute("orders", orders);
		return PAGE_SALES_ORDER_LIST;
	}

	@RequestMapping(value = "/so_details")
	public String showOrderDetails(ModelMap model, @ModelAttribute("orders") Map<SalesOrder, Set<SOStatus>> orders, @RequestParam String id) {

		long orderId = Long.parseLong(id);
		SalesOrder order = salesOrderService.getFromOrdersMap(orders, orderId);

		model.addAttribute("order", order);
		model.addAttribute("toStatus", orders.get(order));
		return PAGE_SALES_ORDER_DETAILS;
	}

	@RequestMapping(value = "/so_search")
	public String searchOrders(ModelMap model, @RequestParam String status, @RequestParam String creator) {

		long creatorId = "".equals(creator) ? -1 : Long.parseLong(creator);
		Map<SalesOrder, Set<SOStatus>> ordersMap = salesOrderService.getOrdersMap(status, creatorId);

		model.addAttribute("orders", ordersMap);
		model.addAttribute("operation", "SEARCH");
		return PAGE_SALES_ORDER_LIST;
	}

	@RequestMapping(value = "/so_status")
	public String changeStatus(ModelMap model, @ModelAttribute("orders") Map<SalesOrder, Set<SOStatus>> orders, @RequestParam String id, @RequestParam String status, @RequestParam String toStatus) {

		long orderId = Long.parseLong(id);
		salesOrderService.changeStatus(orderId, status, toStatus);
		Map<SalesOrder, Set<SOStatus>> ordersMap = salesOrderService.removeFromOrdersMap(orders, orderId);

		model.addAttribute("orders", ordersMap);
		return PAGE_SALES_ORDER_LIST;
	}

	@RequestMapping(value = "/so_search_page")
	public String showPageSearchOrders(ModelMap model) {

		Set<User> retailers = salesOrderService.getAllCreators();
		Set<SOStatus> statuses = salesOrderService.getAllAllowedStatuses();

		model.addAttribute("statuses", statuses);
		model.addAttribute("creators", retailers);
		return PAGE_SALES_ORDER_SEARCH;
	}

	@RequestMapping(value = "/shopping_cart", method = RequestMethod.GET)
	public String shoppingCartList(ModelMap model, @RequestParam(required = false) String id) {
		
		if (id != null && id.matches("[0-9]+")) {

			long productId = Long.parseLong(id);
			Product product = productService.getProduct(productId);
			if (product != null) {
				shoppingCartList.put(product, 1);
			}

			model.addAttribute("shoppingCartList", shoppingCartList);
		}

		return PAGE_SHOPPING_CART;
	}

	@RequestMapping(value = "/shopping_cart_remove", method = RequestMethod.POST)
	public String removeFromShoppingcart(ModelMap model, @RequestParam(required = false) String id) {

		if (id != null && id.matches("[0-9]+")) {
			long productId = Long.parseLong(id);
			Product product = productService.getProduct(productId);
			shoppingCartList.remove(product);
//			model.addAttribute("shoppingCartList", shoppingCartList);
		}

		return PAGE_SHOPPING_CART;
	}

	@RequestMapping(value = "/cancel_order", method = RequestMethod.GET)
	public String cancelOrder(ModelMap model, @RequestParam(required = false) String id) {
		shoppingCartList.clear();
//		model.addAttribute("shoppingCartList", shoppingCartList);
		return "redirect:recent";
	}

	@RequestMapping(value = "/customer_info", method = RequestMethod.GET)
	public String customerInformationPage(ModelMap model) {
		return PAGE_CUSTOMER_INFO;
	}

	@RequestMapping(value = "/customer_info", method = RequestMethod.POST)
	public String customerInformationPagePost(ModelMap model, @RequestParam(required = false) String operation, @RequestParam(required = false) String customerEmail) {
		if (operation.equals("search")) {
			model.addAttribute("operation", "search");
			model.addAttribute("searchResult", profileService.getCustomerByMail(customerEmail));
		}
		return PAGE_CUSTOMER_INFO;
	}

	@RequestMapping(value = "/change_quantity", method = RequestMethod.POST)
	public String changeQuantity(ModelMap model, @RequestParam(required = false) String id,	@RequestParam(required = false) String quantity) {

		if (id != null && id.matches("[0-9]+")) {
			long productId = Long.parseLong(id);
			Product product = productService.getProduct(productId);

			if (quantity != null && quantity.matches("[0-9]+")) {
				shoppingCartList.put(product, Integer.valueOf(quantity));
			}

//			model.addAttribute("shoppingCartList", shoppingCartList);
		}

		return PAGE_SHOPPING_CART;
	}

	@RequestMapping(value = "/update_customer", method = RequestMethod.POST)
	public String updateCustomer(ModelMap model, @RequestParam(required = false) String selectedCustomer) {
		if (selectedCustomer != null && !selectedCustomer.equalsIgnoreCase("")) {
			model.addAttribute("customer", profileService.getCustomer(Long.parseLong(selectedCustomer)));
			model.addAttribute("updateOperation", "true");
			model.addAttribute("enableNextStep", "true");
			model.addAttribute("selectedCustomer", profileService.getCustomer(Long.parseLong(selectedCustomer)));
		} else {
			model.addAttribute("updateOperation", "false");
		}
		return PAGE_CUSTOMER_INFO;
	}

	@RequestMapping(value = "/credit_card_info", method = RequestMethod.GET)
	public String loadCreditCardInfo(ModelMap model) {
		model.addAttribute("enableNextStep", "true");
		model.addAttribute("paymentType", "cash");
		return PAGE_CREDIT_CARD_INFO;
	}

	@RequestMapping(value = "/credit_card_info", method = RequestMethod.POST)
	public String selectPaymentType(ModelMap model, @RequestParam(required = false) String paymentType, HttpSession session) {
		if (paymentType != null && !paymentType.equalsIgnoreCase("")) {
			if (paymentType.equals("cash")) {
				model.addAttribute("paymentType", "cash");
				model.addAttribute("enableNextStep", "true");
			} else if (paymentType.equals("credit")) {
				model.addAttribute("paymentType", "credit");
				Customer c = (Customer) session.getAttribute("selectedCustomer");
				model.addAttribute("customerCreditCards", profileService.getCreditCardByCustomerID(c.getId()));
				model.addAttribute("enableNextStep", "false");
			}
		}
		return PAGE_CREDIT_CARD_INFO;
	}

	@RequestMapping(value = "/credit_card_new", method = RequestMethod.POST)
	public String addNewCreditCard(ModelMap model, HttpSession session) {
		model.addAttribute("addNewCredit", "true");
//		model.addAttribute("paymentType", "credit");
		Customer c = (Customer) session.getAttribute("selectedCustomer");
		model.addAttribute("customerCreditCards", profileService.getCreditCardByCustomerID(c.getId()));
		model.addAttribute("enableNextStep", "false");
		return PAGE_CREDIT_CARD_INFO;
	}

	@RequestMapping(value = "/select_credit_card_item", method = RequestMethod.POST)
	public String selectCreditCard(ModelMap model, @RequestParam(required = false) String selectedCreditCard, HttpSession session) {
		if (selectedCreditCard != null && !selectedCreditCard.equals("")) {
			model.addAttribute("selectedCreditCard", profileService.getCreditCard(Long.parseLong(selectedCreditCard)));
			session.setAttribute("selectedCreditCard", profileService.getCreditCard(Long.parseLong(selectedCreditCard)));
			model.addAttribute("selectCreditCardItem", "true");
			model.addAttribute("enableNextStep", "true");
			model.addAttribute("paymentType", "credit");
		}
		return PAGE_CREDIT_CARD_INFO;
	}

	@RequestMapping(value = "/order_confirmation_page", method = RequestMethod.GET)
	public String orderConfirmationPage(ModelMap model, HttpSession session) {
//		model.addAttribute("shoppingCartList", shoppingCartList);

		long totalPrice = 0;
		for (Product product : shoppingCartList.keySet()) {
			totalPrice += product.getPrice() * (shoppingCartList.get(product));
		}

		model.addAttribute("totalPrice", totalPrice);
		session.setAttribute("totalPrice", totalPrice);
		return PAGE_ORDER_CONFIRMATION_PAGE;
	}

	@RequestMapping(value = "/finish_order", method = RequestMethod.GET)
	public String finishOrder(ModelMap model, @ModelAttribute("shoppingCartList") Map<Product, Integer> shoppingCartList, HttpSession session) {

		 Customer customer = (Customer) session.getAttribute("selectedCustomer");
		
		 CreditCard creditCard=null;
		 if(((String) model.get("paymentType")).equalsIgnoreCase("credit")){
		 creditCard = (CreditCard) session.getAttribute("selectedCreditCard");
		 creditCard.setCustomer(customer);
		 if(customer.getCreditCards() == null)
		 {
		 customer.setCreditCards(new HashSet<CreditCard>());
		 }
		 if(creditCard.getId() == 0){
			 customer.getCreditCards().add(creditCard);
		 }
		 
		 }
		 profileService.addNewCustomer(customer);
		
		 SalesOrder order= new SalesOrder();
		 order.setCustomer(customer);
		
		 Set<SalesOrderItem> orderItems = new HashSet<SalesOrderItem>();
		
		 for(Product product : shoppingCartList.keySet()){
		 SalesOrderItem orderItem = new SalesOrderItem();
		 orderItem.setBook(product);
		 orderItem.setQuantity(shoppingCartList.get(product));
		 orderItem.setOrder(order);
		 orderItems.add(orderItem);
		 }
		 order.setOrderItems(orderItems);
		 order.setGrandTotalPrice((Long)session.getAttribute("totalPrice"));
		 order.setDate(Calendar.getInstance());
		 salesOrderService.addSalesOrder(order);

		shoppingCartList.clear();
		model.addAttribute("orderStatus", "DONE");
		return PAGE_ORDER_CONFIRMATION_PAGE;
	}

}
